package com.gullmall.product.service.impl;

import com.gullmall.common.constant.ProductConstant;
import com.gullmall.common.to.SkuDiscountTo;
import com.gullmall.common.to.SkuHasStockTo;
import com.gullmall.common.to.SpuBoundsTo;
import com.gullmall.common.to.es.SkuEsModel;
import com.gullmall.common.utils.R;
import com.gullmall.product.entity.*;
import com.gullmall.product.feign.CouponClient;
import com.gullmall.product.feign.SearchClient;
import com.gullmall.product.feign.WareClient;
import com.gullmall.product.service.*;
import com.gullmall.product.vo.spu.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gullmall.common.utils.PageUtils;
import com.gullmall.common.utils.Query;

import com.gullmall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

@Slf4j
@Service("spuInfoService")
@Transactional
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Resource(name = "spuInfoDescService")
    private SpuInfoDescService spuInfoDescService;
    @Resource(name = "spuImagesService")
    private SpuImagesService spuImagesService;
    @Resource(name = "productAttrValueService")
    private ProductAttrValueService productAttrValueService;
    @Resource(name = "skuInfoService")
    private SkuInfoService skuInfoService;
    @Resource(name = "skuImagesService")
    private SkuImagesService skuImagesService;
    @Resource(name = "skuSaleAttrValueService")
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Resource(name = "com.gullmall.product.feign.CouponClient")
    private CouponClient couponClient;
    @Resource(name = "categoryService")
    private CategoryService categoryService;
    @Resource(name = "brandService")
    private BrandService brandService;
    @Resource(name = "com.gullmall.product.feign.WareClient")
    private WareClient wareClient;
    @Resource(name = "com.gullmall.product.feign.SearchClient")
    private SearchClient searchClient;
    @Resource(name = "attrService")
    private AttrService attrService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }


    /**
     * 共要操作:
     * gullmall_psm库下的表:
     * pms_spu_info(spu基本信息) , pms_spu_info_desc(spu的描述图片) , pms_spu_images(spu的图片集) ,
     * pms_product_attr_value(spu的规格参数) , pms_sku_info(sku的基本信息) , pms_sku_images(sku的图片信息)
     * , pms_sku_sale_attr_value(sku的销售属性)
     * <p>
     * gullmall_sms库下的表:
     * sms_spu_bounds(spu积分) , sms_sku_ladder(满几件打几折)  sms_sku_full_reduction(满多少钱打几折)
     * sms_member_price(会员打折表)
     */
    @Override
    public R saveSpuInfo(SpuSaveVo spuSaveVo) {
        //1,保存spu基本信息,pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfoEntity);
        this.saveBaseSpuInfo(spuInfoEntity);
        Long spuId = spuInfoEntity.getId();//保存完后ID会回填到实体类中

        //2,保存spu的描述图片.pms_spu_info_desc
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        List<String> description = spuSaveVo.getDecript();
        spuInfoDescEntity.setSpuId(spuId);
        spuInfoDescEntity.setDecript(String.join(",", description));
        spuInfoDescService.save(spuInfoDescEntity);

        //3,保存spu的图片集 pms_spu_images
        List<String> images = spuSaveVo.getImages();//批量保存
        spuImagesService.saveImages(images, spuId);

        //4,保存spu的规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        productAttrValueService.saveBaseAttrs(baseAttrs, spuId);

        //4.1 gullmall_sms库下的 sms_spu_bounds (spu积分,需远程调用)
        //to放在common服务中
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(spuSaveVo.getBounds(), spuBoundsTo);
        spuBoundsTo.setSpuId(spuId);
        if (spuBoundsTo.getBuyBounds().compareTo(new BigDecimal(0)) == 1 || spuBoundsTo.getGrowBounds().compareTo(new BigDecimal(0)) == 1) {
            //远程调用
            //TODO 远程调用失败后的事务
            couponClient.saveSpuBonds(spuBoundsTo);
        }

        //5,保存当前spu对应的sku信息:
        List<Skus> skus = spuSaveVo.getSkus();
        if (!CollectionUtils.isEmpty(skus)) {
            skus.forEach(item -> {
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item, skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSpuId(spuId);

                String defaultImg = "";
                for (Images image : item.getImages()) {
                    if (image.getDefaultImg() == 1) {
                        defaultImg = image.getImgUrl();
                    }
                }
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                //--5.1 sku的基本信息 pms_sku_info
                skuInfoService.save(skuInfoEntity);

                Long skuId = skuInfoEntity.getSkuId();
                List<SkuImagesEntity> skuImagesEntityList = item.getImages().stream()
                        .filter(img -> !StringUtils.isEmpty(img.getImgUrl()))
                        .map(img -> {
                            SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                            skuImagesEntity.setSkuId(skuId);
                            skuImagesEntity.setImgUrl(img.getImgUrl());
                            skuImagesEntity.setDefaultImg(img.getDefaultImg());
                            return skuImagesEntity;
                        }).collect(Collectors.toList());
                //--5.2 sku的图片信息 pms_sku_images
                skuImagesService.saveBatch(skuImagesEntityList);

                //--5.3 sku的销售属性 pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();//销售属性
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntityList = attrs.stream().map(attr -> {
                    SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                    skuSaleAttrValueEntity.setSkuId(skuId);
                    return skuSaleAttrValueEntity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntityList);
                //--5.4 sku的优惠信息 gullmall_sms库下的
                //    sms_sku_ladder(满几件打几折)  sms_sku_full_reduction(满多少钱打几折)
                //    sms_member_price(会员打折表)
                SkuDiscountTo skuDiscountTo = new SkuDiscountTo();
                BeanUtils.copyProperties(item, skuDiscountTo);
                skuDiscountTo.setSkuId(skuId);
                if (skuDiscountTo.getFullCount() > 0 || skuDiscountTo.getFullPrice().compareTo(new BigDecimal(0)) == 1) {
                    //远程调用
                    //TODO 远程调用失败后的事务
                    couponClient.saveSkuDiscount(skuDiscountTo);
                }

            });
        }
        return R.ok();
    }

    @Override
    public Boolean saveBaseSpuInfo(SpuInfoEntity spuInfoEntity) {
        return this.save(spuInfoEntity);
    }

    /**
     * @param params {t=1655260120983, status=新建/上架/下架, key=, brandId=0
     *               , catelogId=960, page=1, limit=10}
     */
    @Override
    public PageUtils querySpuinfoPageByCondition(Map<String, Object> params) {

        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            queryWrapper.like("spu_name", key);
        }
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            queryWrapper.eq("publish_status", status);
        }
        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(params.get("brandId")) && !"0".equals(brandId)) {
            queryWrapper.eq("brand_id", brandId);
        }
        String catelogId = (String) params.get("catelogId");
        if (!StringUtils.isEmpty(catelogId) && !"0".equals(catelogId)) {
            queryWrapper.eq("catalog_id", params.get("catelogId"));
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                queryWrapper
        );
        return new PageUtils(page);
    }

    /**
     * 上架SPU
     *
     * @param spuId
     */
    @Override
    public R up(Long spuId) {
        //查出当前spu对应的所有sku
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkuBySpuId(spuId);
        //查出当前spu的brandId和catalogId,为了获取brandName和catalogName
        SpuInfoEntity spuInfoEntity = this.getById(spuId);
        Long spuCatalogId = spuInfoEntity.getCatalogId();
        Long spuBrandId = spuInfoEntity.getBrandId();
        //获取所属分类
        CategoryEntity categoryEntity = categoryService.getById(spuCatalogId);
        //获取匹配封面
        BrandEntity brandEntity = brandService.getById(spuBrandId);
        //获取spu的属性
        List<ProductAttrValueEntity> productAttrValueEntity = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));

        //过滤出所有attr_id
        List<Long> attrIds = productAttrValueEntity.stream().map(m -> m.getAttrId()).collect(Collectors.toList());
        //获取允许被搜索的属性的id(即attr表中search_type为1的字段)
        Set<Long> allowSearchAttrIds = new HashSet<Long>(attrService.selectSearchAttrIds(attrIds));

        List<SkuEsModel.Attrs> attrsList = productAttrValueEntity.stream()
                .filter(f -> allowSearchAttrIds.contains(f.getAttrId()))
                .map(p -> {
                    SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
                    attrs.setAttrId(p.getAttrId());
                    attrs.setAttrName(p.getAttrName());
                    attrs.setAttrValue(p.getAttrValue());
                    return attrs;
                }).collect(Collectors.toList());

        //获取所有skuId
        List<Long> skuIds = skuInfoEntities.stream().
                map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        Map<Long, Boolean> skuHasStockToMap = null;
        try {
            //远程调用ware服务,查看是否有库存
            List<SkuHasStockTo> skuHasStockTo = wareClient.getSkuHasStock(skuIds);
            //list转为map
            skuHasStockToMap = skuHasStockTo.stream().
                    collect(Collectors.toMap(k -> k.getSkuId(), v -> v.getHasStock()));//k什么作为key,v什么作为value

        } catch (Exception e) {
            log.error("ware调用有异常{}", e);

        }
        //封装每个sku的信息
        Map<Long, Boolean> finalSkuHasStockToMap = skuHasStockToMap;
        List<SkuEsModel> SkuEsModels = skuInfoEntities.stream().map(m -> {
                    SkuEsModel skuEsModel = new SkuEsModel();
                    BeanUtils.copyProperties(m, skuEsModel);
                    //不一样的字段单独设置
                    skuEsModel.setAttrs(attrsList);
                    skuEsModel.setSkuPrice(m.getPrice());
                    skuEsModel.setSkuImg(m.getSkuDefaultImg());
                    //TODO 1,热度评分hotScore字段,类似竞价排名,这里暂且先默认0
                    skuEsModel.setHotScore(0L);
                    skuEsModel.setBrandName(brandEntity.getName());
                    skuEsModel.setBrandImg(brandEntity.getLogo());
                    skuEsModel.setCatalogName(categoryEntity.getName());
                    if (finalSkuHasStockToMap == null) {//远程调用失败,或者查不到
                        skuEsModel.setHasStock(false);
                    } else {
                        skuEsModel.setHasStock(finalSkuHasStockToMap.get(m.getSkuId()) == null ? false : finalSkuHasStockToMap.get(m.getSkuId()));
                    }
                    return skuEsModel;
                }
        ).collect(Collectors.toList());

        //发送给es保存,远程调用search服务
        R r = searchClient.productStatusUp(SkuEsModels);
        if (r.getCode() == 0) {
            //es保存成功
            //修改spu状态为已上架
            SpuInfoEntity updateStatus = new SpuInfoEntity();
            updateStatus.setId(spuId);
            updateStatus.setPublishStatus(ProductConstant.SpuStatusEnum.UP_STATUS.getCode());
            this.updateById(updateStatus);
        } else {
            //es保存失败
        }
        return R.ok().put("data", SkuEsModels);
    }


}